{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "parameters"
    ]
   },
   "outputs": [],
   "source": [
    "epochs = 10\n",
    "n_test_batches = 200"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Part 11 - ডিপ লার্নিং ক্লাসিফিকেশন সুরক্ষিত করুন (Secure Deep Learning Classification) \n",
    "\n",
    "\n",
    "\n",
    "## আপনার ডেটা গুরুত্বপূর্ণ, আপনার মডেলও (Your data matters, your model too)\n",
    "\n",
    "ডেটা মেশিন লার্নিংয়ের পিছনে চালক । সংস্থাগুলি যারা ডেটা তৈরি এবং সংগ্রহ করে তাদের নিজস্ব মেশিন লার্নিং মডেলগুলি তৈরি এবং প্রশিক্ষণ দিতে সক্ষম। এটি তাদের বাহ্যিক সংস্থাগুলিতে পরিষেবা (MLaaS) হিসাবে যেমন মডেলগুলির ব্যবহারের প্রদান করতে দেয়। এটি অন্যান্য সংস্থাগুলি হিসাবে দরকারী যারা সম্ভবত এই মডেলগুলি নিজেরাই তৈরি করতে সক্ষম না হতে পারে তবে যারা এখনও তাদের নিজস্ব ডেটা নিয়ে ভবিষ্যদ্বাণী করতে এই মডেলটি ব্যবহার করতে চান।\n",
    "\n",
    "তবে মেঘে(cloud) হোস্ট করা একটি মডেল এখনও একটি গোপনীয়তা / আইপি ইস্যু (privacy/IP issue) উপস্থাপন করে। বাহ্যিক সংস্থাগুলি এটি ব্যবহার করার জন্য - তাদের অবশ্যই তাদের ইনপুট ডেটা (যেমন চিত্রগুলি শ্রেণিবদ্ধ করার জন্য) আপলোড করতে হবে বা মডেলটি ডাউনলোড করতে হবে। গোপনীয়তার দৃষ্টিকোণ থেকে ইনপুট ডেটা আপলোড করা সমস্যাযুক্ত হতে পারে তবে মডেলটি তৈরি / মালিকানাধীন সংস্থা তাদের আইপি(IP) হারাতে উদ্বিগ্ন হলে মডেলটি ডাউনলোড করা কোনও বিকল্প হতে পারে না। \n",
    "\n",
    "## এনক্রিপ্ট করা ডেটা ওপরে গণনা করা (Computing over encrypted data)\n",
    "\n",
    "এই প্রসঙ্গে, একটি সম্ভাব্য সমাধান হ'ল মডেল এবং তথ্য উভয়কে এমনভাবে এনক্রিপ্ট করা যা কোনও সংস্থা তাদের আইপি প্রকাশ না করেই অন্য সংস্থার মালিকানাধীন একটি মডেল ব্যবহার করতে দেয়। বেশ কয়েকটি এনক্রিপশন স্কিম বিদ্যমান যা এনক্রিপ্ট হওয়া ডেটাগুলিতে গণনার অনুমতি দেয়, যার মধ্যে সিকিউর মাল্টি-পার্টির গণনা (এসএমপিসি/SMPC), হোমোমর্ফিক এনক্রিপশন (FHE/SHE) এবং ফাংশনাল এনক্রিপশন (FE) সর্বাধিক পরিচিত প্রকারগুলি। আমরা এখানে সুরক্ষিত মাল্টি পার্টি পার্টি গণনা উপর ফোকাস করব ([introduced in detail here in tutorial 5](https://github.com/OpenMined/PySyft/blob/dev/examples/tutorials/Part%205%20-%20Intro%20to%20Encrypted%20Programs.ipynb)) যা বেসরকারী সংযোজন ভাগ করে নিয়ে গঠিত। এটি সিকিউরএনএন(SecureNN) এবং এসপিডিজেডের (SPDZ) মতো ক্রিপ্টো প্রোটোকলগুলির উপর নির্ভর করে, এর বিবরণ দেওয়া আছে [in this excellent blog post](https://mortendahl.github.io/2017/09/19/private-image-analysis-with-mpc/). \n",
    "\n",
    "এই প্রোটোকলগুলি এনক্রিপ্ট করা ডেটাগুলির চেয়ে দুর্দান্ত পারফরম্যান্স অর্জন করে এবং বিগত কয়েকমাস ধরে আমরা এই প্রোটোকলগুলি ব্যবহার সহজ করার জন্য কাজ করে যাচ্ছি। বিশেষত, আমরা নিজেরাই প্রোটোকলটি পুনরায় প্রয়োগ না করে আপনাকে এই প্রোটোকলগুলি ব্যবহার করার অনুমতি দেওয়ার জন্য সরঞ্জামগুলি তৈরি করছি (বা এটি কীভাবে কাজ করে তার পিছনে ক্রিপ্টোগ্রাফিও জেনে রাখা উচিত)। আসুন সরাসরি লাফ দিন।\n",
    "\n",
    "## সেট আপ করুন (Set up)\n",
    "\n",
    "এই টিউটোরিয়ালে হুবহু সেটিংটি হল: আপনি সার্ভার এবং আপনার কাছে কিছু ডেটা রয়েছে তা বিবেচনা করুন। প্রথমে, আপনি এই ব্যক্তিগত প্রশিক্ষণের ডেটা দিয়ে একটি মডেল সংজ্ঞায়িত এবং প্রশিক্ষণ দিন। তারপরে, আপনি এমন কোনও ক্লায়েন্টের সংস্পর্শে আসেন যিনি তাদের নিজস্ব কিছু ডেটা রাখেন যিনি কিছু ভবিষ্যদ্বাণী করতে আপনার মডেলটি অ্যাক্সেস করতে চান।\n",
    "\n",
    "আপনি আপনার মডেলটি এনক্রিপ্ট করেছেন (একটি নিউরাল নেটওয়ার্ক)। ক্লায়েন্ট (client) তাদের ডেটা এনক্রিপ্ট করে। আপনি উভয়ই ডেটা শ্রেণিবদ্ধ করার জন্য এই দুটি এনক্রিপ্ট করা সম্পদ ব্যবহার করেন। শেষ অবধি, ভবিষ্যদ্বাণীটির ফলাফলটি একটি এনক্রিপ্ট করা (encrypted) উপায়ে ক্লায়েন্টকে ফেরত পাঠানো হয় যাতে সার্ভার (_i.e._ আপনি) ক্লায়েন্টের ডেটা সম্পর্কে কিছুই জানতে না (আপনি ইনপুট বা ভবিষ্যদ্বাণীও শিখেন না)।\n",
    "\n",
    "আদর্শভাবে আমরা যুক্ত করে ভাগ করে নিই `client`'s নিজের এবং এর মধ্যে ইনপুট`server` এবং মডেল জন্য বিপরীতে। সরলতার জন্য, শেয়ারগুলি অন্য দুই শ্রমিকের হাতে থাকবে `alice` and `bob`. আপনি যদি বিবেচনা করেন যে alice ক্লায়েন্টের মালিকানাধীন এবং সার্ভারের দ্বারা bob এটি সম্পূর্ণ সমতুল্য।\n",
    "\n",
    "গণনাটি সৎ-তবে-কৌতূহল বিদ্বেষী মডেলটিতে সুরক্ষিত যা মান এখানে [many MPC frameworks](https://arxiv.org/pdf/1801.03239.pdf).\n",
    "\n",
    "**আমাদের এখন যা প্রয়োজন তা আমাদের কাছে আছে, আসুন শুরু করা যাক!**\n",
    "\n",
    "\n",
    "Author:\n",
    "- Théo Ryffel - Twitter: [@theoryffel](https://twitter.com/theoryffel) · GitHub: [@LaRiffle](https://github.com/LaRiffle)\n",
    "\n",
    "**চলুন শুরু করা যাক (Let's get started!)**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "অনুবাদক:\n",
    "\n",
    "- Sourav Das - Twitter: [@adventuroussrv](https://twitter.com/adventuroussrv)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### আমদানি এবং মডেল বিশেষ উল্লেখ (Imports and model specifications)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "import torch.optim as optim\n",
    "from torchvision import datasets, transforms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আমাদের পাইসাইফ্ট আমদানি / শুরু করার জন্য নির্দিষ্ট কমান্ডগুলি কার্যকর করতে হবে। আমরা কয়েক জন কর্মী তৈরি করেছি (নামকরণ করেছি `client`, `bob`, and `alice`). শেষ পর্যন্ত, আমরা সংজ্ঞা `crypto_provider` আমাদের প্রয়োজন হতে পারে সমস্ত ক্রিপ্টো প্রাক্কালীন কে দেয়([See our tutorial on SMPC for more details](https://github.com/OpenMined/PySyft/blob/master/examples/tutorials/Part%2009%20-%20Intro%20to%20Encrypted%20Programs.ipynb)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "import syft as sy\n",
    "hook = sy.TorchHook(torch) \n",
    "client = sy.VirtualWorker(hook, id=\"client\")\n",
    "bob = sy.VirtualWorker(hook, id=\"bob\")\n",
    "alice = sy.VirtualWorker(hook, id=\"alice\")\n",
    "crypto_provider = sy.VirtualWorker(hook, id=\"crypto_provider\") "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আমরা শেখার কাজটির সেটিংটি সংজ্ঞায়িত করি"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Arguments():\n",
    "    def __init__(self):\n",
    "        self.batch_size = 64\n",
    "        self.test_batch_size = 50\n",
    "        self.epochs = epochs\n",
    "        self.lr = 0.001\n",
    "        self.log_interval = 100\n",
    "\n",
    "args = Arguments()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ডেটা লোড করা এবং কর্মীদের কাছে প্রেরণ (Data loading and sending to workers\n",
    "\n",
    "আমাদের সেটিংয়ে, আমরা ধরে নিই যে সার্ভারটির মডেলটি প্রথমে প্রশিক্ষণের জন্য কিছু ডেটা অ্যাক্সেস করেছে। এখানে এমএনআইএসটি(MNIST) প্রশিক্ষণের সেট (training set) রয়েছে।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "train_loader = torch.utils.data.DataLoader(\n",
    "    datasets.MNIST('../data', train=True, download=True,\n",
    "                   transform=transforms.Compose([\n",
    "                       transforms.ToTensor(),\n",
    "                       transforms.Normalize((0.1307,), (0.3081,))\n",
    "                   ])),\n",
    "    batch_size=args.batch_size, shuffle=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "দ্বিতীয়ত, ক্লায়েন্টের কিছু ডেটা রয়েছে এবং এটি সার্ভারের মডেলটি ব্যবহার করে ভবিষ্যদ্বাণী করতে চান। এই ক্লায়েন্টটি এটিকে যুক্ত করে দুটি কর্মী- alice এবং bob জুড়ে ভাগ করে এটির ডেটা এনক্রিপ্ট করে\n",
    "> SMPC ক্রিপ্টো প্রোটোকল ব্যবহার করে যার জন্য পূর্ণসংখ্যার উপর কাজ করা প্রয়োজন।  .fix_precision()  ব্যবহার করে পাইটর্চ ফ্লোট টেনেসরগুলিকে স্থির যথার্থ টেনেসরে রূপান্তর করতে আমরা পাইসাইফ্ট টেনসর বিমূর্ততাটি এখানে পেয়েছি ` উদাহরণস্বরূপ 0.123 যথার্থতা 2 সহ দ্বিতীয় দশমিক অঙ্কে একটি বৃত্তাকার করে তাই সঞ্চিত সংখ্যাটি পূর্ণসংখ্যা 12 হয়।\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_loader = torch.utils.data.DataLoader(\n",
    "    datasets.MNIST('../data', train=False,\n",
    "                   transform=transforms.Compose([\n",
    "                       transforms.ToTensor(),\n",
    "                       transforms.Normalize((0.1307,), (0.3081,))\n",
    "                   ])),\n",
    "    batch_size=args.test_batch_size, shuffle=True)\n",
    "\n",
    "private_test_loader = []\n",
    "for data, target in test_loader:\n",
    "    private_test_loader.append((\n",
    "        data.fix_precision().share(alice, bob, crypto_provider=crypto_provider),\n",
    "        target.fix_precision().share(alice, bob, crypto_provider=crypto_provider)\n",
    "    ))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### ফরোয়ার্ড নিউরাল নেটওয়ার্ক স্পেসিফিকেশন ফিড (Feed Forward Neural Network specification)\n",
    "সার্ভার দ্বারা ব্যবহৃত নেটওয়ার্ক স্পেসিফিকেশন এখানে"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Net(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(Net, self).__init__()\n",
    "        self.fc1 = nn.Linear(784, 500)\n",
    "        self.fc2 = nn.Linear(500, 10)\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = x.view(-1, 784)\n",
    "        x = self.fc1(x)\n",
    "        x = F.relu(x)\n",
    "        x = self.fc2(x)\n",
    "        return x"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### প্রশিক্ষণ চালু করুন (Launch the training)\n",
    "প্রশিক্ষণ স্থানীয়ভাবে করা হয় তাই এটি খাঁটি স্থানীয় পাইটর্চ প্রশিক্ষণ, এখানে বিশেষ কিছু নেই!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train(args, model, train_loader, optimizer, epoch):\n",
    "    model.train()\n",
    "    for batch_idx, (data, target) in enumerate(train_loader):\n",
    "        optimizer.zero_grad()\n",
    "        output = model(data)\n",
    "        output = F.log_softmax(output, dim=1)\n",
    "        loss = F.nll_loss(output, target)\n",
    "        loss.backward()\n",
    "        optimizer.step()\n",
    "        if batch_idx % args.log_interval == 0:\n",
    "            print('Train Epoch: {} [{}/{} ({:.0f}%)]\\tLoss: {:.6f}'.format(\n",
    "                epoch, batch_idx * args.batch_size, len(train_loader) * args.batch_size,\n",
    "                100. * batch_idx / len(train_loader), loss.item()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = Net()\n",
    "optimizer = torch.optim.Adam(model.parameters(), lr=args.lr)\n",
    "\n",
    "for epoch in range(1, args.epochs + 1):\n",
    "    train(args, model, train_loader, optimizer, epoch)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(args, model, test_loader):\n",
    "    model.eval()\n",
    "    test_loss = 0\n",
    "    correct = 0\n",
    "    with torch.no_grad():\n",
    "        for data, target in test_loader:\n",
    "            output = model(data)\n",
    "            output = F.log_softmax(output, dim=1)\n",
    "            test_loss += F.nll_loss(output, target, reduction='sum').item() # sum up batch loss\n",
    "            pred = output.argmax(1, keepdim=True) # get the index of the max log-probability \n",
    "            correct += pred.eq(target.view_as(pred)).sum().item()\n",
    "\n",
    "    test_loss /= len(test_loader.dataset)\n",
    "\n",
    "    print('\\nTest set: Average loss: {:.4f}, Accuracy: {}/{} ({:.0f}%)\\n'.format(\n",
    "        test_loss, correct, len(test_loader.dataset),\n",
    "        100. * correct / len(test_loader.dataset)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test(args, model, test_loader)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "আমাদের মডেল এখন প্রশিক্ষিত এবং একটি পরিষেবা হিসাবে সরবরাহের জন্য প্রস্তুত!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## নিরাপদ মূল্যায়ন (Secure evaluation)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "এখন, সার্ভার হিসাবে, আমরা তথ্য ধারণকারী কর্মীদের কাছে মডেলটি প্রেরণ করি। কারণ মডেলটি সংবেদনশীল তথ্য (আপনি এটির অনুকূলকরণের জন্য সময় ব্যয় করেছেন!), আপনি এর ওজনগুলি প্রকাশ করতে চান না যাতে আপনি গোপনে মডেলটি ভাগ করে নেন ঠিক যেমন আমরা আগে ডেটাসেটের সাথে করেছি।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "model.fix_precision().share(alice, bob, crypto_provider=crypto_provider)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "এই পরীক্ষার কার্যটি এনক্রিপ্ট করা মূল্যায়ন করে। মডেল ওজন, ডেটা ইনপুট, ভবিষ্যদ্বাণী এবং স্কোরিংয়ের জন্য ব্যবহৃত লক্ষ্যগুলি এনক্রিপ্ট করা আছে!\n",
    "\n",
    "তবে সিনট্যাক্সটি কোনও মডেলের খাঁটি পাইটর্চ পরীক্ষার সাথে খুব মিল, এটি কি সুন্দর ?!\n",
    "\n",
    "ভবিষ্যদ্বাণীগুলি গড়ে ভাল ছিল কিনা তা যাচাই করার জন্য সার্ভারের দিক থেকে আমরা একমাত্র ডিক্রিপ্ট করি শেষে চূড়ান্ত স্কোর।"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(args, model, test_loader):\n",
    "    model.eval()\n",
    "    n_correct_priv = 0\n",
    "    n_total = 0\n",
    "    with torch.no_grad():\n",
    "        for data, target in test_loader[:n_test_batches]:\n",
    "            output = model(data)\n",
    "            pred = output.argmax(dim=1) \n",
    "            n_correct_priv += pred.eq(target.view_as(pred)).sum()\n",
    "            n_total += args.test_batch_size\n",
    "# This 'test' function performs the encrypted evaluation. The model weights, the data inputs, the prediction and the target used for scoring are all encrypted!\n",
    "\n",
    "# However as you can observe, the syntax is very similar to normal PyTorch testing! Nice!\n",
    "\n",
    "# The only thing we decrypt from the server side is the final score at the end of our 200 items batches to verify predictions were on average good.      \n",
    "            n_correct = n_correct_priv.copy().get().float_precision().long().item()\n",
    "    \n",
    "            print('Test set: Accuracy: {}/{} ({:.0f}%)'.format(\n",
    "                n_correct, n_total,\n",
    "                100. * n_correct / n_total))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test(args, model, private_test_loader)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Et voilà!  আপনি এখানে আছেন, নিরাপদ পূর্বাভাস শেষ করতে কীভাবে করবেন তা শিখলেন: সার্ভারের মডেলের ওজন ক্লায়েন্টের কাছে ফাঁস হয়নি এবং সার্ভারের ডেটা ইনপুট বা শ্রেণিবদ্ধকরণ আউটপুট সম্পর্কে কোনও তথ্য নেই!\n",
    "\n",
    "পারফরম্যান্স সম্পর্কে, একটি চিত্রের শ্রেণিবদ্ধকরণ এর চেয়ে কম নেয় 0.1 সেকেন্ড। প্রায় 33ms আমার ল্যাপটপে  (2,7 GHz Intel Core i7, 16GB RAM) তবে, এটি খুব দ্রুত যোগাযোগ ব্যবহার করছে (সমস্ত কর্মী আমার স্থানীয় মেশিনে আছেন) বিভিন্ন কর্মীরা একে অপরের সাথে কীভাবে কথা বলতে পারে তার উপর নির্ভর করে পারফরম্যান্স পরিবর্তিত হবে।"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## উপসংহার (Conclusion)\n",
    "\n",
    "আপনি দেখেছেন যে পাইটর্চ এবং পাইসাইফ্টের সুবিধা অর্জন করা কতটা সহজ ব্যবহারিক সিকিউর মেশিন শিখতে এবং ব্যবহারকারীদের ডেটা সুরক্ষিত করতে, কোনও ক্রিপ্টো বিশেষজ্ঞ না হয়ে!\n",
    "\n",
    "এই বিষয়টিতে আরও শীঘ্রই আসবে, অন্যান্য লাইব্রেরির ক্ষেত্রে পাই সাইফট পারফরম্যান্সকে যথাযথভাবে বেনমার্ক করার জন্য কনভোলশিয়াল স্তরগুলি সহ,পাশাপাশি নিউরাল নেটওয়ার্কগুলির বেসরকারী এনক্রিপ্ট করা প্রশিক্ষণ, যখন কোনও সংস্থা যখন তার নিজস্ব মডেলটি প্রশিক্ষণের জন্য বাহ্যিক সংবেদনশীল ডেটাতে রিসর্ট করে তখন প্রয়োজনীয় হয়। সাথে থাকুন!\n",
    "\n",
    "আপনি যদি এটি উপভোগ করেন এবং গোপনীয়তা সংরক্ষণ, AI এবং AI সরবরাহ চেইনের (ডেটা) বিকেন্দ্রীভূত মালিকানার দিকে আন্দোলনে যোগ দিতে চান, আপনি নিম্নলিখিত উপায়ে এটি করতে পারেন!\n",
    "\n",
    "### গিটহাবে পাইসিফ্ট কে স্টার দিন (Star PySyft on GitHub)\n",
    "\n",
    "আমাদের সম্প্রদায়কে সাহায্য করার সবচেয়ে সহজ উপায় হ'ল রিপোসিটোরি গুলোতে ষ্টার করা\n",
    " এটি আমরা যে অসাধারণ সরঞ্জামগুলি তৈরি করছি তার সচেতনতা বাড়াতে সহায়তা করে।\n",
    "\n",
    "- [Star PySyft](https://github.com/OpenMined/PySyft)\n",
    "\n",
    "### গিটহাবে আমাদের টিউটোরিয়ালগুলি চয়ন করুন (Pick our tutorials on GitHub!)\n",
    "\n",
    "ফেডারেটেড এবং প্রাইভেসি-প্রিজারভেভিং লার্নিংয়ের চেহারা কেমন হওয়া উচিত এবং আমরা এটির জন্য ইটগুলি কীভাবে তৈরি করছি সে সম্পর্কে আরও ভাল ধারণা পেতে আমরা সত্যিই দুর্দান্ত টিউটোরিয়াল তৈরি করেছি।\n",
    "\n",
    "- [Checkout the PySyft tutorials](https://github.com/OpenMined/PySyft/tree/master/examples/tutorials)\n",
    "\n",
    "\n",
    "### আমাদের স্ল্যাক যোগ দিন (Join our Slack!)\n",
    "\n",
    "সর্বশেষতম অগ্রগতিতে আপ টু ডেট রাখার সর্বোত্তম উপায় হ'ল আমাদের সম্প্রদায়ে যোগদান করা!\n",
    "\n",
    "- [Join slack.openmined.org](http://slack.openmined.org)\n",
    "\n",
    "### একটি কোড প্রকল্পে যোগদান করুন (Join a Code Project!)\n",
    "\n",
    "আমাদের সম্প্রদায়ে অবদান রাখার সর্বোত্তম উপায় হল কোড অবদানকারী হয়ে উঠুন! আপনি যদি মিনি-প্রকল্পগুলি \"ওয়ান অফ\" শুরু করতে চান তবে আপনি পাইসাইফ্ট গিটহাব ইস্যু পৃষ্ঠাতে গিয়ে চিহ্নিত বিষয়গুলির জন্য অনুসন্ধান করতে পারেন `Good First Issue`.\n",
    "\n",
    "- [Good First Issue Tickets](https://github.com/OpenMined/PySyft/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)\n",
    "\n",
    "### দান করা (Donate)\n",
    "\n",
    "আপনার যদি আমাদের কোডবেসে অবদান রাখার সময় না থাকে তবে তবুও সমর্থন দিতে চান, আপনি আমাদের ওপেন কালেক্টিভেরও Backer হয়ে উঠতে পারেন। সমস্ত অনুদান আমাদের ওয়েব হোস্টিং এবং অন্যান্য সম্প্রদায় ব্যয় যেমন হ্যাকাথনস এবং মেটআপগুলির (hackathons and meetups!) দিকে যায়!\n",
    "\n",
    "- [Donate through OpenMined's Open Collective Page](https://opencollective.com/openmined)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "celltoolbar": "Tags",
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  },
  "nbTranslate": {
   "displayLangs": [
    "*"
   ],
   "hotkey": "alt-t",
   "langInMainMenu": true,
   "sourceLang": "en",
   "targetLang": "fr",
   "useGoogleTranslate": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
